package com.jackie.coupon.customer.service.impl;

import com.google.common.collect.Lists;
import com.jackie.coupon.customer.api.bean.SearchCoupon;
import com.jackie.coupon.customer.api.dto.calc.ShoppingCart;
import com.jackie.coupon.customer.api.dto.calc.SimulationOrder;
import com.jackie.coupon.customer.api.dto.calc.SimulationResponse;
import com.jackie.coupon.customer.api.dto.template.beans.CouponInfo;
import com.jackie.coupon.customer.api.dto.template.beans.CouponTemplateInfo;
import com.jackie.coupon.customer.convertor.CouponConverter;
import com.jackie.coupon.customer.dao.CouponDao;
import com.jackie.coupon.customer.dao.entity.Coupon;
import com.jackie.coupon.customer.api.bean.RequestCoupon;
import com.jackie.coupon.customer.service.CouponCustomerService;
import com.jackie.coupon.customer.api.enumss.CouponStatus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * CouponCustomerServiceImpl
 *
 * @author Jackie Hou
 * @date 2023/11/19 11:10
 * @version 1.0
 */
@Service
@Slf4j
public class CouponCustomerServiceImpl implements CouponCustomerService {

    @Override
    public Coupon requestConpon(RequestCoupon request) {
//        CouponTemplateInfo templateInfo = couponTemplateService.loadTemplateInfo(request.getCouponTemplateId());

        //改成远程调用
        CouponTemplateInfo templateInfo = webClientBuilder.build()
                .get()
                .uri("http://coupon-template-serv/template/getTemplate?id=" + request.getCouponTemplateId())
                .retrieve()
                .bodyToMono(CouponTemplateInfo.class)
                .block();

        if (templateInfo == null) {
            log.error("templateInfo not found! templatedId = {}", request.getCouponTemplateId());
            throw new IllegalArgumentException("Invalid template id");
        }

        //模板不能过期且有效
        long now = Calendar.getInstance().getTimeInMillis();
        Long expireTime = templateInfo.getRule().getDeadline();
        if (expireTime != null && now >= expireTime || BooleanUtils.isFalse(templateInfo.getAvailable())) {
            log.error("template is not available! id= {}", request.getCouponTemplateId());
            throw new IllegalArgumentException("template is unavailable!");
        }

        Long count = couponDao.countByUserIdAndTemplateId(request.getUserId(), request.getCouponTemplateId());
        if (count >= templateInfo.getRule().getLimitation()) {
            log.error("max count is overflow!");
            throw new IllegalArgumentException("max count is overflow");
        }

        Coupon coupon = Coupon.builder()
                .templateId(request.getCouponTemplateId())
                .userId(request.getUserId())
                .shopId(templateInfo.getShopId())
                .status(CouponStatus.AVAILABLE)
                .build();

        return coupon;
    }

    @Override
    public ShoppingCart placeOrder(ShoppingCart cart) {
        return null;
    }

    @Override
    public SimulationResponse simulateOrderPrice(SimulationOrder order) {
        return null;
    }

    @Override
    public void deleteCoupon(Long userId, Long couponId) {

    }

    @Override
    public List<CouponInfo> findCoupon(SearchCoupon request) {

        Coupon example = Coupon.builder()
                .userId(request.getUserId())
                .status(CouponStatus.convert(request.getCouponStatus()))
                .shopId(request.getShopId())
                .build();

        List<Coupon> coupons = couponDao.findAll(Example.of(example));
        if (coupons.isEmpty()) {
            return Lists.newArrayList();
        }

        List<Long> templateIds = coupons.stream()
                .map(Coupon :: getTemplateId)
                .collect(Collectors.toList());
//        Map<Long, CouponTemplateInfo> templateInfoMap = couponTemplateService.getTemplateInfoMap(templateIds);
        Map<Long, CouponTemplateInfo> templateInfoMap = webClientBuilder.build()
                .get()
                .uri("http://coupon-template-serv/template/getBatch?ids=" + templateIds)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Map<Long, CouponTemplateInfo>>() {})
                .block();

        coupons.stream().forEach(
                e -> e.setTemplateInfo(templateInfoMap.get(e.getTemplateId()))
        );

        return coupons.stream()
                .map(CouponConverter :: convert2Coupon)
                .collect(Collectors.toList());
    }

    @Autowired
    private CouponDao couponDao;

//    @Autowired
//    private CouponTemplateService couponTemplateService;

    @Autowired
    private WebClient.Builder webClientBuilder;
}
